#include "spritex.h"


SpriteX::SpriteX(const string&filename)
{
    loadSpx(filename);
}

SpriteX::~SpriteX()
{
    clear();
}

void SpriteX::clear()
{
    header = 0;
    version = 0;
    byteorder = 0;
    tileCount = 0;
    frameCount = 0;
    actionCount = 0;

    tileList.clear();
    frameList.clear();
    actionList.clear();
}

bool SpriteX::loadSpx(const string&file)
{
    clear();

    ifstream in(file.c_str(),ios_base::binary);
    if( !in.is_open() ){
        cerr << "Error open file " << file << endl;
        return  false;
    }

    in.read((char*)&header,4);
    in.read((char*)&version,1);
    in.read((char*)&byteorder,1);

    tile_t tile;
    in.read((char*)&tileCount,4);
    if( tileCount > 0 ){
        tileList.resize(tileCount);
    }
    for( int i = 0 ; i <tileCount ; i ++ ){
        if( !getTile(in,tile) ){
            cerr << "Get tile error" << endl;
            return  false;
        }
        tileList[i] = tile;
    }

    frame_t frame;
    in.read((char*)&frameCount,4);
    if( frameCount > 0 ){
        frameList.resize(frameCount);
    }
    for( int i = 0 ; i < frameCount ; i ++ ){
        if( !getFrame(in,frame) ){
            cerr << "Get frame error" << endl;
            return false;
        }
        frameList[i] = frame;
    }

    action_t action;
    in.read((char*)&actionCount,4);
    if( actionCount > 0 ){
        actionList.resize(actionCount);
    }
    for( int i = 0 ; i < actionCount ; i ++ ){
        if( !getAction(in,action) ){
            cerr << "Get Action Error" << endl;
            return false;
        }
        actionList[i] = action;
    }

    in.close();

    return  true;
}


bool SpriteX::getTile(ifstream&in,tile_t&t)
{
    in.read((char*)&t.x,2);
    in.read((char*)&t.y,2);
    in.read((char*)&t.w,2);
    in.read((char*)&t.h,2);
    return true;
}

bool SpriteX::getFrame(ifstream&in,frame_t&f)
{
    int frameTileCount = 0;
    int collisionCount = 0;
    int referCount = 0;

    in.read((char*)&frameTileCount,4);
    in.read((char*)&collisionCount,4);
    in.read((char*)&referCount,4);
    f.hdr.length = 8 + 4*( frameTileCount +
                           collisionCount ) + 2* referCount;
    f.hdr.tileCount = (short)frameTileCount;
    f.hdr.collisionCount = (short)collisionCount;
    f.hdr.referCount = (short)referCount;

    in.read((char*)&f.hdr.top,2);
    in.read((char*)&f.hdr.buttom,2);
    in.read((char*)&f.hdr.left,2);
    in.read((char*)&f.hdr.right,2);

    f.data.tile.resize(frameTileCount);
    f.data.collision.resize(collisionCount);
    f.data.refer.resize(referCount);

    for( int i = 0 ; i < frameTileCount ; i ++ ){
        in.read((char*)&f.data.tile[i].index,2);
        in.read((char*)&f.data.tile[i].x,2);
        in.read((char*)&f.data.tile[i].y,2);
        in.read((char*)&f.data.tile[i].transform,2);
    }

    for( int i = 0 ; i < collisionCount ; i ++ ){
        in.read((char*)&f.data.collision[i].x,2);
        in.read((char*)&f.data.collision[i].y,2);
        in.read((char*)&f.data.collision[i].w,2);
        in.read((char*)&f.data.collision[i].h,2);
    }

    for( int i = 0 ;i < referCount ; i ++ ){
        in.read((char*)&f.data.refer[i].x,2);
        in.read((char*)&f.data.refer[i].y,2);
    }

    return true;
}

bool SpriteX::getAction(ifstream&in,action_t&a)
{
    int seqcount = 0;
    unsigned char hasdelay = 0;
    int transform = 0;
    in.read((char*)&seqcount,4);
    in.read((char*)&hasdelay,1);
    in.read((char*)&transform,4);
    a.hdr.sequencecount = (short)seqcount;
    a.hdr.hasdelay = (short)hasdelay;
    a.hdr.transform = (short)transform;

    if( a.hdr.hasdelay == 1 )
        a.hdr.length = 4 + 2 * a.hdr.sequencecount;
    else
        a.hdr.length = 4 + a.hdr.sequencecount;

    a.data.seq.resize(a.hdr.sequencecount);
    if( a.hdr.hasdelay == 1 ){
        for( int i = 0 ; i < a.hdr.sequencecount ; i ++ ){
            in.read((char*)&a.data.seq[i].sequence,2);
            in.read((char*)&a.data.seq[i].delaytime,2);
        }
    }else{
        for( int i = 0 ; i < a.hdr.sequencecount ; i ++ ){
            in.read((char*)&a.data.seq[i].sequence,2);
            a.data.seq[i].delaytime = -1;
        }
    }

    return true;
}


